package com.luke.boot.spring_security.config;

import com.luke.boot.spring_security.util.MD5Util;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * WebSecurity配置类
 */
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) //开启方法权限控制（代替URL资源和权限绑定）
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //定义用户详情服务（查询用户信息）
    //可以通过自定义UserDetailsService实现类，实现从数据库查询用户信息，参考MyUserDetailService.java
    /*@Bean
    public UserDetailsService userDetailsService(){
        System.out.println("--------------userDetailsService------------");
        //基于内存存储用户信息
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("zhangsan").password("202cb962ac59075b964b07152d234b70").authorities("p1").build());//密码123
        manager.createUser(User.withUsername("lisi").password("250cf8b51c773f3f8dc8b4be867a9a02").authorities("p2").build());//密码456
        return manager;
    }*/

    //密码编码器（前端传输的是明文，后端存储的是密文）
    @Bean
    public PasswordEncoder passwordEncoder() {
        /*return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                //将前端明文（rawPassword）加密后和后端密文（encodedPassword）进行比较，相等则认证成功
                return encodedPassword.equals(MD5Util.encode((String) rawPassword));
            }
        };*/
        return new BCryptPasswordEncoder();//内置的密码编码器
    }

    //安全拦截机制（核心）
    //SpringSecurity提供的默认登录页面地址为/login，登出地址为/logout
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//关闭CSRF
                .authorizeRequests()
                //注意：精确的匹配放前面
                /*.antMatchers("/r/r1").hasAuthority("p1")//资源和权限绑定
                .antMatchers("/r/r2").hasAuthority("p2")//资源和权限绑定*/
                .antMatchers("/r/**").authenticated()///请求路径r/**，必须先认证
                .anyRequest().permitAll()//其他可以任意访问
                .and()
                .formLogin()//允许通过表单方式登录
                .successForwardUrl("/login-success") //自定义登录成功后的页面地址
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); //会话创建策略（分布式环境采用Token，不使用Session）
    }

}
